<template>
    <div class="_fc_fetch">
        <el-row :gutter="10">
            <el-col :span="24">
                <el-form-item label="选择接口" style="margin-bottom: 18px">
                    <jd-select v-model="dataValue" :apiObj="$API.app.interface.list" :apiProps="{label: 'remark', value: 'id'}" style="width: 100%;" clearable placeholder="请选择..." @change="changeDataValue"></jd-select>
                </el-form-item>
            </el-col>
            <!-- <el-col :span="24">
                <el-form-item label="默认值" style="margin-bottom: 18px">
                    <jd-select v-model="defaultValue" :apiObj="$API.app.interface.get" :params="{id: dataValue}" clearable filterable style="width: 100%;" placeholder="请选择..." @change="changeDataDefault"></jd-select>
                </el-form-item>
            </el-col> -->
        </el-row>
        <el-row :gutter="10" v-if="dataValue!=''">
            <el-col :span="12">
                <el-form-item label="解析函数" style="margin-bottom: 18px">
                    <el-switch v-model="isParse" @change="switchParse"></el-switch>
                </el-form-item>
            </el-col>
            <el-col :span="12" align="right">
                <el-form-item style="padding-top: 28px" v-if="isParse">
                    <el-button @click="visible=true" style="width: 100%;">编辑函数</el-button>
                </el-form-item>
            </el-col>
        </el-row>
        <ElDialog title="编辑函数" v-model="visible" :close-on-click-modal="false" append-to-body>
            <div ref="editor" v-if="visible"></div>
            <template #footer>
                <span class="dialog-footer">
                    <span class="_fc_err" v-if="err">
                        {{ t('struct.error') }}{{ err !== true ? err : '' }}</span>
                    <ElButton @click="visible = false">{{ t('struct.cancel') }}</ElButton>
                    <ElButton type="primary" @click="onOk">{{ t('struct.submit') }}</ElButton>
                </span>
            </template>
        </ElDialog>
        <DragForm v-model:api="api" :modelValue="formValue" :rule="rule" :option="option" @change="input"/>
    </div>
</template>

<script>
import 'codemirror/lib/codemirror.css';
import CodeMirror from 'codemirror/lib/codemirror';
import 'codemirror/mode/javascript/javascript';
import debounce from '@form-create/utils/lib/debounce';
import is from '@form-create/utils/lib/type';
import {designerForm} from '../utils/form';
import {defineComponent} from 'vue';
import sysConfig from "@/config";
import tool from '@/utils/tool';

export default defineComponent({
    name: 'Fetch',
    props: {
        modelValue: [Object, String],
        to: String,
    },
    components: {
        DragForm: designerForm.$form(),
    },
    inject: ['designer'],
    computed: {
        formValue() {
            const val = this.modelValue;
            if (!val) return {};
            if (is.String(val)) {
                return {
                    action: val
                };
            }
            if (!val._parse && val.parse) {
                return {...val, _parse: '' + val.parse};
            } else if (is.Function(val._parse)) {
                return {...val, _parse: '' + val._parse};
            }
            return val;
        }
    },
    data() {
        const t = this.designer.setupState.t;
        return {
            api: {},
            fetch: {},
            t,
            editor: null,
            visible: false,
            err: false,
            dataValue: "",
            defaultValue: "",
            isParse: false,
            option: {
                form: {

                },
                submitBtn: false,
            },
            rule: [
                {
                    type: 'input',
                    field: 'action',
                    title: t('fetch.action') + ': ',
                    hidden: true,
                },
                {
                    type: 'select',
                    field: 'method',
                    title: t('fetch.method') + ': ',
                    hidden: true,
                    value: 'GET',
                    options: [
                        {label: 'GET', value: 'GET'},
                        {label: 'POST', value: 'POST'},
                    ],
                    control: [
                        {
                            value: 'POST',
                            rule: [
                                {
                                    type: 'select',
                                    field: 'dataType',
                                    title: t('fetch.dataType') + ': ',
                                    hidden: true,
                                    value: 'JSON',
                                    options: [
                                        {label: 'FormData', value: 'FormData'},
                                        {label: 'JSON', value: 'JSON'},
                                    ]
                                },
                            ]
                        }
                    ]
                },
                {
                    type: 'Struct',
                    field: 'data',
                    title: t('fetch.data') + ': ',
                    value: {},
                    hidden: true,
                    props: {
                        defaultValue: {},
                    }
                },
                {
                    type: 'Struct',
                    field: 'headers',
                    title: t('fetch.headers') + ': ',
                    value: {},
                    hidden: true,
                    props: {
                        defaultValue: {},
                    }
                },
                {
                    type: 'input',
                    field: '_parse',
                    value: 'function (res){\n   return res.data;\n}',
                    hidden: true,
                    props: {
                        type: 'textarea',
                        rows: 8,
                        readonly: true
                    },
                },
            ],
        };
    },
    created() {
        if (!Array.isArray(this.modelValue)) {
            this.$emit('input', []);
        }
    },
    watch: {
        visible(n) {
            if (n) {
                this.loadParse();
            } else {
                this.err = false;
            }
        }
    },
    methods: {
        // 选择接口
        changeDataValue(dataId){
            // 清空默认值
            this.defaultValue = '';
            this.modelValue.data.defaultValue = '';
            // 加载数据
            this.setData(dataId);
        },
        // 默认选中
        changeDataDefault(value){
            // 设置默认值
            this.defaultValue = value;
            this.modelValue.data.defaultValue = value;
            // 设置选择项
            this.designer.setupState.activeRule.value = value;
            // 加载数据
            //this.setDict(this.dataValue);
        },
        switchParse(value){
            if (value){
                this.rule[5].hidden = false;
                this.modelValue.data.isParse = false;
            } else {
                this.rule[5].hidden = true;
                this.modelValue.data.isParse = true;
            }
        },
        loadParse() {
            this.$nextTick(() => {
                this.editor = CodeMirror(this.$refs.editor, {
                    lineNumbers: true,
                    mode: 'javascript',
                    gutters: ['CodeMirror-lint-markers'],
                    lint: true,
                    line: true,
                    tabSize: 2,
                    lineWrapping: true,
                    value: this.modelValue._parse || ''
                });
            });
        },
        onOk() {
            if (this.err) return;
            const str = this.editor.getValue();
            let val;
            try {
                val = eval('(function (){return ' + str + '}())');
            } catch (e) {
                this.err = ` (${e})`;
                return;
            }
            if (this.validate && false === this.validate(val)) {
                this.err = true;
                return;
            }
            this.visible = false;
            this.modelValue._parse = str;
            this.$emit('update:modelValue._parse', val);
        },
        setData(dataId){
            this.api.submit((formData) => {
                formData.data = {
                    id: dataId,
                    defaultValue: this.defaultValue,
                    dataValue: this.dataValue,
                    isParse: this.isParse
                }

                formData.dataType = "JSON",
                formData.to = this.to || 'options';
                formData.method = 'POST';
                formData.action = this.$API.app.interface.test.url;

                // 设置请求头
                let token = tool.cookie.get("TOKEN");
                formData.headers[sysConfig.TOKEN_NAME] = sysConfig.TOKEN_PREFIX + token;

                // 设置解析函数
                formData._parse = 
`function (res){
   return res.data.data.map(row=>{
       return {
           label: row.name,
           value: row.desc
       }
   })
}`;

                // 更新组件的值
                this.$emit('update:modelValue', formData);
            });
        },
        parseFn(v) {
            return eval(`(function () {
                return ${v}
            })()`);
        },
        _input() {
            this.api.submit((formData) => {
                formData.to = this.to || 'options';
                if (formData._parse) formData.parse = this.parseFn(formData._parse);
                this.$emit('update:modelValue', formData);
            });
        },
        input: debounce(function () {
            this._input();
        }, 50),
    },
    mounted() {
        if (this.modelValue){
            this.dataValue = this.modelValue.data.dataValue !=null ? this.modelValue.data.dataValue : '';
            this.defaultValue = this.modelValue.data.defaultValue !=null ? this.modelValue.data.defaultValue : '';
            this.isParse = this.modelValue.data.isParse !=null ? this.modelValue.data.isParse : false;
            if (this.isParse){
                this.rule[5].hidden = false;
            }
        }
        this._input();
    }
});
</script>
<style>
._fc_fetch .el-form-item{
    margin: 0px;
    padding: 0px;
    margin-bottom: 18px;
}
</style>
